from flask import request, jsonify, g, Blueprint
from datetime import datetime, timedelta
import jwt

from global_scope import get_bcrypt, get_auth, get_db, SECRET_KEY, TOKEN_EXPIRE
from tools import token_required, log_operations
from project_model import User, TokenRecord

bcrypt = get_bcrypt()
auth = get_auth()
db = get_db()

auth_bp = Blueprint("auth", __name__, url_prefix='/auth')


@auth.verify_password
def verify_password(username, password):
    """
    验证用户名和密码。

    :param username: 用户名
    :param password: 密码
    :return: 验证通过的用户对象或None
    """
    user = User.query.filter_by(username=username).first()
    if user and bcrypt.check_password_hash(user.password, password):
        return user


@auth_bp.route('/login', methods=['POST'])
@log_operations
def login():
    """
    登录接口。

    :return: 登录响应
    """
    data = request.get_json()
    username = data.get('username')
    password = data.get('password')

    if not username or not password:
        return jsonify({"error": "Username and password required"}), 400

    user = verify_password(username, password)
    if not user:
        return jsonify({'error': 'Invalid username or password'}), 400

    role = user.roles[0].id if user.roles else None
    token = jwt.encode({
        'id': user.id,
        'exp': datetime.utcnow() + timedelta(hours=TOKEN_EXPIRE),
        'current_role': role
    }, SECRET_KEY, algorithm="HS256")

    token_record = TokenRecord(token=token, user_id=user.id)
    db.session.add(token_record)
    db.session.commit()

    resp = {
        "code": 0,
        "message": "OK",
        "data": {
            "accessToken": token
        },
        "originUrl": "/auth/login"
    }
    return jsonify(resp), 200


@auth_bp.route('/refresh/token', methods=['GET'])
@log_operations
def refresh_token():
    """
    登录接口。

    :return: 登录响应
    """
    token = jwt.encode({
        'id': g.user_id,
        'exp': datetime.utcnow() + timedelta(hours=TOKEN_EXPIRE),
        'current_role': g.current_role
    }, SECRET_KEY, algorithm="HS256")

    token_record = TokenRecord(token=token, user_id=g.user_id)
    db.session.add(token_record)
    db.session.delete(g.token)
    db.session.commit()

    resp = {
        "code": 0,
        "message": "OK",
        "data": {
            "accessToken": token
        },
        "originUrl": "/refresh/token"
    }
    return jsonify(resp), 200


@auth_bp.route(
    '/current-role/switch/<string:role_code>', methods=['POST'])
@log_operations
@token_required
def switch_role(role_code):
    """
    切换角色接口。

    :param role_code: 角色代码
    :return: 切换角色响应
    """
    user = db.session.get(User, g.user_id)
    if not user:
        return jsonify(
            {"code": 1, "message": "User not found", "originUrl": request.path}), 404

    current_role_id = next((role.id for role in user.roles if role.code == role_code), None)

    if current_role_id is not None:
        token = jwt.encode({
            'id': user.id,
            'exp': datetime.utcnow() + timedelta(hours=TOKEN_EXPIRE),
            'current_role': current_role_id
        }, SECRET_KEY, algorithm="HS256")

        token_record = TokenRecord(token=token, user_id=user.id)
        db.session.add(token_record)
        db.session.delete(g.token)
        db.session.commit()
    else:
        return jsonify(
            {"code": 1, "message": "Role not switch", "originUrl": request.path}), 404

    response_data = {
        'code': 0,
        'message': 'OK',
        'data': {
            'accessToken': token
        },
        'originUrl': f'/current-role/switch/{role_code}'
    }

    return jsonify(response_data), 200


@auth_bp.route('/logout', methods=['POST'])
@log_operations
@token_required
def logout():
    """
    登出接口。

    :return: 登出响应
    """
    if g.token:
        db.session.delete(g.token)
        db.session.commit()
        return jsonify({
            'code': 0,
            'message': 'OK',
            'data': True,
            'originUrl': '/logout'
        }), 200
    return jsonify({"error": "Invalid token"}), 401
